﻿using GrayParrot.Configuration;
using GrayParrot.Communications.Configuration;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net.Configuration;
using System.Net.Mail;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace GrayParrot.Communications.Email
{
    public class Mailing : INotifier
    {
        public static MailSettings Settings { get; set; }
        public static Dictionary<string, string> Templates { get; set; }

        //public static bool SendNotification(string from, List<string> to, List<string> cc, string subject, string message)
        //{
        //	return SendNotification(from, to, cc, subject, message, null);
        //}

        //public static bool SendNotification(string from, List<string> to, List<string> cc, string subject, string template, Dictionary<string, string> templateValues)
        //{
        //	bool result = true;
        //	MailSettingsSectionGroup mailSettings = default(MailSettingsSectionGroup);

        //	if (string.IsNullOrEmpty(from))
        //	{
        //		throw new NotificationException(string.Format("Parameter [{0}] is null or empty", "from"));
        //	}

        //	if (string.IsNullOrEmpty(subject))
        //	{
        //		throw new NotificationException(string.Format("Parameter [{0}] is null or empty", "subject"));
        //	}

        //	if (string.IsNullOrEmpty(template))
        //	{
        //		throw new NotificationException(string.Format("Parameter [{0}] is null or empty", "template"));
        //	}

        //	if ((to == null || to.Count == 0) && (cc == null || cc.Count == 0))
        //	{
        //		throw new NotificationException("Specify at least one mail address in the parameters [to] or [cc]Parameter [{0}] is null or empty");
        //	}

        //	if (string.IsNullOrEmpty(template))
        //	{
        //		throw new NotificationException(string.Format("Parameter [{0}] is null or empty", "template"));
        //	}



        //	if (Mailing.Settings == default(MailSettings))
        //	{
        //		try
        //		{
        //			if (System.Web.HttpContext.Current != null)
        //			{
        //				mailSettings = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~").GetSectionGroup("system.net/mailSettings") as MailSettingsSectionGroup;
        //			}
        //			else
        //			{
        //				mailSettings = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).GetSectionGroup("system.net/mailSettings") as MailSettingsSectionGroup;
        //			}

        //			//mailSettings = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).GetSectionGroup("system.net/mailSettings") as MailSettingsSectionGroup;

        //			/*
        //			<mailSettings>
        //				<smtp from="assistenza@betpointstaff.it">
        //					<network host="172.16.200.50" port="25" userName="noreply@betpointstaff.it" password="noreply" defaultCredentials="true"/>
        //				</smtp>
        //			</mailSettings>
        //		 */

        //			Mailing.Settings = new MailSettings();

        //			Mailing.Settings.Host = mailSettings.Smtp.Network.Host; //ConfigurationManager.AppSettings["MailServer"];
        //			Mailing.Settings.Port = mailSettings.Smtp.Network.Port; //int.Parse(ConfigurationManager.AppSettings["MailPort"]);

        //			Mailing.Settings.UseDefaultCredentials = mailSettings.Smtp.Network.DefaultCredentials;
        //			Mailing.Settings.Credential = new System.Net.NetworkCredential() { UserName = mailSettings.Smtp.Network.UserName, Password = mailSettings.Smtp.Network.Password };

        //			Mailing.Settings.IsSSLEnabled = mailSettings.Smtp.Network.EnableSsl; //Convert.ToBoolean(ConfigurationManager.AppSettings["IsSSLEnabled"].ToString());
        //		}
        //		catch
        //		{
        //			throw new NotificationException("Error reading mailsettings section group from file config");
        //		}
        //	}



        //	try
        //	{
        //		MailMessage msg = new MailMessage();
        //		msg.From = new MailAddress(from); //"<a href="mailto:noreply@server.com">noreply@server.com</a>"
        //		msg.DeliveryNotificationOptions = DeliveryNotificationOptions.None;


        //		if (to != null && to.Count > 0)
        //		{
        //			foreach (var mail in to)
        //			{
        //				msg.To.Add(mail); //"<a href="mailto:noreply@server.com">noreply@server.com</a>"
        //			}
        //		}


        //		if (cc != null && cc.Count > 0)
        //		{
        //			foreach (var mail in cc)
        //			{
        //				msg.CC.Add(mail); //"<a href="mailto:noreply@server.com">noreply@server.com</a>"
        //			}
        //		}



        //		msg.Subject = subject;
        //		msg.Body = GetMailBody(template, templateValues);
        //		msg.IsBodyHtml = true;

        //		// your remote SMTP server IP.
        //		SmtpClient smtp = new SmtpClient();
        //		smtp.Host = Mailing.Settings.Host; //ConfigurationManager.AppSettings["MailServer"];
        //		smtp.UseDefaultCredentials = Mailing.Settings.UseDefaultCredentials;
        //		smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
        //		if (Mailing.Settings.UseDefaultCredentials)
        //		{
        //			smtp.Credentials = Mailing.Settings.Credential;
        //		}

        //		smtp.Port = Mailing.Settings.Port; //int.Parse(ConfigurationManager.AppSettings["MailPort"]);
        //		smtp.EnableSsl = Mailing.Settings.IsSSLEnabled; //Convert.ToBoolean(ConfigurationManager.AppSettings["IsSSLEnabled"].ToString());


        //		smtp.Send(msg);
        //	}
        //	catch (Exception ex)
        //	{
        //		result = false;
        //	}

        //	return result;
        //}

        private string GetMailBody(string template, Dictionary<string, string> templateValues)
        {
            string body = default(string);

            if (!string.IsNullOrEmpty(template))
            {
                body = template;

                if (templateValues != null && templateValues.Count > 0)
                {
                    foreach (string key in templateValues.Keys)
                    {
                        body = body.Replace(key, templateValues[key]);
                    }
                }
            }

            return body;
        }

        /// <summary>
        /// Determines whether [is valid email] [the specified email].
        /// </summary>
        /// <param name="email">The email.</param>
        /// <returns></returns>
        private bool IsValidEmail(string email)
        {
            bool retValue = false;

            string pattern = null;
            pattern = "^([0-9a-zA-Z]([-\\.\\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\\w]*[0-9a-zA-Z]\\.)+[a-zA-Z]{2,9})$";

            if (Regex.IsMatch(email, pattern))
            {
                retValue = true;
            }

            return retValue;
        }

        /// <summary>
        /// Sends the specified from.
        /// </summary>
        /// <param name="from">From.</param>
        /// <param name="to">To.</param>
        /// <param name="cc">The cc.</param>
        /// <param name="subject">The subject.</param>
        /// <param name="message">The message.</param>
        /// <returns></returns>
        /// <remarks>
        /// Used to send simple email,
        /// Specify from, to, cc, subject and email body
        /// </remarks>
        public bool Send(string from, List<string> to, List<string> cc, string subject, string message)
        {
            return Send(from, to, cc, subject, message, null);
        }

        /// <summary>
        /// Sends the specified from.
        /// </summary>
        /// <param name="from">From.</param>
        /// <param name="to">To.</param>
        /// <param name="cc">The cc.</param>
        /// <param name="subject">The subject.</param>
        /// <param name="dispositionNotificationTo">The disposition notification to.</param>
        /// <param name="template">The template.</param>
        /// <param name="templateValues">The template values.</param>
        /// <returns></returns>
        /// <exception cref="NotificationException">
        /// Specify at least one mail address in the parameters [to] or [cc]Parameter [{0}] is null or empty
        /// or
        /// or
        /// Error reading mailsettings section group from file config
        /// </exception>
        public bool Send(string from, List<string> to, List<string> cc, string subject, string template, Dictionary<string, string> templateValues)
        {
            bool result = true;
            MailSettingsSectionGroup mailSettings = default(MailSettingsSectionGroup);

            if (string.IsNullOrEmpty(from))
            {
                throw new NotificationException(string.Format("Parameter [{0}] is null or empty", "from"));
            }

            if (string.IsNullOrEmpty(subject))
            {
                throw new NotificationException(string.Format("Parameter [{0}] is null or empty", "subject"));
            }

            if (string.IsNullOrEmpty(template))
            {
                throw new NotificationException(string.Format("Parameter [{0}] is null or empty", "template"));
            }

            if ((to == null || to.Count == 0) && (cc == null || cc.Count == 0))
            {
                throw new NotificationException("Specify at least one mail address in the parameters [to] or [cc]Parameter [{0}] is null or empty");
            }

            if (string.IsNullOrEmpty(template))
            {
                throw new NotificationException(string.Format("Parameter [{0}] is null or empty", "template"));
            }

            //
            if (Mailing.Settings == default(MailSettings))
            {
                try
                {
                    if (System.Web.HttpContext.Current != null)
                    {
                        mailSettings = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~").GetSectionGroup("system.net/mailSettings") as MailSettingsSectionGroup;
                    }
                    else
                    {
                        mailSettings = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).GetSectionGroup("system.net/mailSettings") as MailSettingsSectionGroup;
                    }

                    /*
                    <mailSettings>
                        <smtp from="assistenza@betpointstaff.it">
                            <network host="172.16.200.50" port="25" userName="noreply@betpointstaff.it" password="noreply" defaultCredentials="true"/>
                        </smtp>
                    </mailSettings>
                 */

                    Mailing.Settings = new MailSettings();

                    Mailing.Settings.Host = mailSettings.Smtp.Network.Host; //ConfigurationManager.AppSettings["MailServer"];
                    Mailing.Settings.Port = mailSettings.Smtp.Network.Port; //int.Parse(ConfigurationManager.AppSettings["MailPort"]);

                    Mailing.Settings.UseDefaultCredentials = mailSettings.Smtp.Network.DefaultCredentials;
                    Mailing.Settings.Credential = new System.Net.NetworkCredential() { UserName = mailSettings.Smtp.Network.UserName, Password = mailSettings.Smtp.Network.Password };

                    Mailing.Settings.IsSSLEnabled = mailSettings.Smtp.Network.EnableSsl; //Convert.ToBoolean(ConfigurationManager.AppSettings["IsSSLEnabled"].ToString());
                }
                catch
                {
                    throw new NotificationException("Error reading mailsettings section group from file config");
                }
            }

            CommunicationsSettings m_commCfg = null;
            ConfigurationManagerHelper pp = new ConfigurationManagerHelper();
            m_commCfg = pp.GetCommunicationsSettings();

            try
            {
                MailMessage msg = new MailMessage();
                msg.From = new MailAddress(from); //"<a href="mailto:noreply@server.com">noreply@server.com</a>"
                
                if (to != null && to.Count > 0)
                {
                    foreach (var mail in to)
                    {
                        msg.To.Add(mail); //"<a href="mailto:noreply@server.com">noreply@server.com</a>"

                        msg.ReplyToList.Add(mail);
                    }
                }

                if (cc != null && cc.Count > 0)
                {
                    foreach (var mail in cc)
                    {
                        msg.CC.Add(mail); //"<a href="mailto:noreply@server.com">noreply@server.com</a>"
                    }
                }
                
                msg.Subject = subject;
                msg.Body = GetMailBody(template, templateValues);
                msg.IsBodyHtml = true;


                if ((m_commCfg != null) && (m_commCfg.EmailSettings != null) && (m_commCfg.EmailSettings.EmailDeliverySettings != null))
                {
                    if (m_commCfg.EmailSettings.EmailDeliverySettings.RequireDeliverySuccessReceipt)
                    {
                        //msg.DeliveryNotificationOptions = msg.DeliveryNotificationOptions | DeliveryNotificationOptions.OnSuccess;
                        msg.DeliveryNotificationOptions = DeliveryNotificationOptions.OnSuccess;
                    }

                    //if (m_commCfg.EmailSettings.EmailDeliverySettings.RequireDeliveryErrorReceipt)
                    //{
                    //    msg.DeliveryNotificationOptions = msg.DeliveryNotificationOptions | DeliveryNotificationOptions.OnFailure;
                    //}

                    // Delivery notifications
                    //msg.DeliveryNotificationOptions =
                    //  DeliveryNotificationOptions.OnFailure |
                    //  DeliveryNotificationOptions.OnSuccess |
                    //  DeliveryNotificationOptions.Delay;

                    if (m_commCfg.EmailSettings.EmailDeliverySettings.RequireReadReceipt)
                    {
                        // se è definito l'indirizzo email a cui inviare i delivery recepits...
                        if (IsValidEmail(m_commCfg.EmailSettings.EmailDeliverySettings.DispositionNotificationTo))
                        {
                            // Ask for a read receipt...
                            msg.Headers.Add("Disposition-Notification-To", m_commCfg.EmailSettings.EmailDeliverySettings.DispositionNotificationTo);
                        }
                    }
                }
                else
                {
                    msg.DeliveryNotificationOptions = DeliveryNotificationOptions.None;
                }

                SmtpClient smtp = new SmtpClient();
                smtp.Host = Mailing.Settings.Host;
                smtp.UseDefaultCredentials = Mailing.Settings.UseDefaultCredentials;
                smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
                if (Mailing.Settings.UseDefaultCredentials)
                {
                    smtp.Credentials = Mailing.Settings.Credential;
                }

                smtp.Port = Mailing.Settings.Port;
                smtp.EnableSsl = Mailing.Settings.IsSSLEnabled;
                
                smtp.Send(msg);
            }
            catch (Exception ex)
            {
                string msg = ex.Message;
                result = false;
                throw;
            }

            return result;
        }
    }
}
